using System.Net;

namespace Century.EnterpriseLibrary.GeoIP
{
	public class MaxMindCountrySearch : ICountrySearch
	{
		private static readonly string[] CountyCodes = new string[]
		{
			string.Empty, 
			"AP", 
			"EU", 
			"AD", 
			"AE", 
			"AF", 
			"AG", 
			"AI", 
			"AL", 
			"AM", 
			"AN", 
			"AO", 
			"AQ", 
			"AR", 
			"AS", 
			"AT", 
			"AU", 
			"AW", 
			"AZ", 
			"BA", 
			"BB", 
			"BD", 
			"BE", 
			"BF", 
			"BG", 
			"BH", 
			"BI", 
			"BJ", 
			"BM", 
			"BN", 
			"BO", 
			"BR", 
			"BS", 
			"BT", 
			"BV", 
			"BW", 
			"BY", 
			"BZ", 
			"CA", 
			"CC", 
			"CD", 
			"CF", 
			"CG", 
			"CH", 
			"CI", 
			"CK", 
			"CL", 
			"CM", 
			"CN", 
			"CO", 
			"CR", 
			"CU", 
			"CV", 
			"CX", 
			"CY", 
			"CZ", 
			"DE", 
			"DJ", 
			"DK", 
			"DM", 
			"DO", 
			"DZ", 
			"EC", 
			"EE", 
			"EG", 
			"EH", 
			"ER", 
			"ES", 
			"ET", 
			"FI", 
			"FJ", 
			"FK", 
			"FM", 
			"FO", 
			"FR", 
			"FX", 
			"GA", 
			"GB", 
			"GD", 
			"GE", 
			"GF", 
			"GH", 
			"GI", 
			"GL", 
			"GM", 
			"GN", 
			"GP", 
			"GQ", 
			"GR", 
			"GS", 
			"GT", 
			"GU", 
			"GW", 
			"GY", 
			"HK", 
			"HM", 
			"HN", 
			"HR", 
			"HT", 
			"HU", 
			"ID", 
			"IE", 
			"IL", 
			"IN", 
			"IO", 
			"IQ", 
			"IR", 
			"IS", 
			"IT", 
			"JM", 
			"JO", 
			"JP", 
			"KE", 
			"KG", 
			"KH", 
			"KI", 
			"KM", 
			"KN", 
			"KP", 
			"KR", 
			"KW", 
			"KY", 
			"KZ", 
			"LA", 
			"LB", 
			"LC", 
			"LI", 
			"LK", 
			"LR", 
			"LS", 
			"LT", 
			"LU", 
			"LV", 
			"LY", 
			"MA", 
			"MC", 
			"MD", 
			"MG", 
			"MH", 
			"MK", 
			"ML", 
			"MM", 
			"MN", 
			"MO", 
			"MP", 
			"MQ", 
			"MR", 
			"MS", 
			"MT", 
			"MU", 
			"MV", 
			"MW", 
			"MX", 
			"MY", 
			"MZ", 
			"NA", 
			"NC", 
			"NE", 
			"NF", 
			"NG", 
			"NI", 
			"NL", 
			"NO", 
			"NP", 
			"NR", 
			"NU", 
			"NZ", 
			"OM", 
			"PA", 
			"PE", 
			"PF", 
			"PG", 
			"PH", 
			"PK", 
			"PL", 
			"PM", 
			"PN", 
			"PR", 
			"PS", 
			"PT", 
			"PW", 
			"PY", 
			"QA", 
			"RE", 
			"RO", 
			"RU", 
			"RW", 
			"SA", 
			"SB", 
			"SC", 
			"SD", 
			"SE", 
			"SG", 
			"SH", 
			"SI", 
			"SJ", 
			"SK", 
			"SL", 
			"SM", 
			"SN", 
			"SO", 
			"SR", 
			"ST", 
			"SV", 
			"SY", 
			"SZ", 
			"TC", 
			"TD", 
			"TF", 
			"TG", 
			"TH", 
			"TJ", 
			"TK", 
			"TM", 
			"TN", 
			"TO", 
			"TL", 
			"TR", 
			"TT", 
			"TV", 
			"TW", 
			"TZ", 
			"UA", 
			"UG", 
			"UM", 
			"US", 
			"UY", 
			"UZ", 
			"VA", 
			"VC", 
			"VE", 
			"VG", 
			"VI", 
			"VN", 
			"VU", 
			"WF", 
			"WS", 
			"YE", 
			"YT", 
			"RS", 
			"ZA", 
			"ZM", 
			"ME", 
			"ZW", 
			"A1", 
			"A2", 
			"O1", 
			"AX", 
			"GG", 
			"IM", 
			"JE", 
			"BL", 
			"MF"
		};
		private byte[] countryDatabase;
		private static long IPAddressToLong(IPAddress addr)
		{
			long num = 0L;
			byte[] addressBytes = addr.GetAddressBytes();
			for (int i = 0; i < 4; i++)
			{
				long num2 = (long)((ulong)addressBytes[i]);
				if (num2 < 0L)
				{
					num2 += 256L;
				}
				num += num2 << (3 - i) * 8;
			}
			return num;
		}
		public MaxMindCountrySearch(byte[] countryDatabase)
		{
			this.countryDatabase = countryDatabase;
		}
		private int SeekCountryCode(long ipAddress)
		{
			int num = 0;
			byte[] array = this.countryDatabase;
			for (int i = 31; i >= 0; i--)
			{
				int num2 = 6 * num;
				long num3 = (long)((int)array[num2] + ((int)array[num2 + 1] << 8) + ((int)array[num2 + 2] << 16));
				long num4 = (long)((int)array[num2 + 3] + ((int)array[num2 + 4] << 8) + ((int)array[num2 + 5] << 16));
				if ((ipAddress & 1L << (i & 31)) > 0L)
				{
					if (num4 >= 16776960L)
					{
						return (int)(num4 - 16776960L);
					}
					num = (int)num4;
				}
				else
				{
					if (num3 >= 16776960L)
					{
						return (int)(num3 - 16776960L);
					}
					num = (int)num3;
				}
			}
			return 0;
		}
		internal void UpdateDatabase(byte[] countryDatabase)
		{
			if (countryDatabase == null)
			{
				throw new System.ArgumentException("countryDatabase");
			}
			this.countryDatabase = countryDatabase;
		}
		public string GetCountryCode(string ipAddress)
		{
			IPAddress address;
			try
			{
				address = IPAddress.Parse(ipAddress);
			}
			catch (System.FormatException)
			{
				return string.Empty;
			}
			return this.GetCountryCode(address);
		}
		public string GetCountryCode(IPAddress address)
		{
			int num = this.SeekCountryCode(MaxMindCountrySearch.IPAddressToLong(address));
			return MaxMindCountrySearch.CountyCodes[num];
		}
	}
}
